package model

import static groovyx.gpars.GParsPool.withPool
import groovy.transform.CompileStatic
import model.agent.*
import view.plotter.PlotManager
import view.plotter.Plotter


class Model {
	//===========全局参数===========
	// 固定随机种子
	static int SEED_FIXED = 1
	static int SEED = 1

	static Random rnd

	static int H_NUM = 200
	static int F_NUM = 20

	static int DAYS_OF_MONTH = 20

	//===========企业参数===============
	static int FULL_MONTHS = 24		//连续多少个月满员，则降工资

	static float MAX_WAGE_GROWTH_RATE = 0.019	//工资增速上限

	static float MAX_PRICE_GROWTH_RATE = 0.02

	//存货调整的上下限调整系数
	static float UPPER_IV_FACTOR = 1
	static float LOWER_IV_FACTOR = 0.25

	static float UPPER_PRICE_FACTOR = 1.15
	static float LOWER_PRICE_FACTOR = 1.025

	static float TECHNOLOGY = 1.2

	//===========家庭参数===============
	static int SHOPPING_FIRMS_NUM = 10

	static float CONSUMPTION_FACTOR = 0.9

	static float PRICE_SEARCH_RATE = 0.25 //寻找更优价格的概率
	static float DEMAND_SEARCH_RATE = 0.25

	static float BETTER_PRICE_FACTOR = 0.01

	static float HIGHER_WAGE_SEARCH_RATE = 0.1

	// 添加
	static float MPC = 1


	int runs = 20 * 12 * 10


	//public static  cores = 4
	ArrayList<HouseHold> households = new ArrayList<HouseHold>()
	ArrayList<Firm> firms = new ArrayList<Firm>()


	public int monthDay

	int ticks = 0

	Thread th

	PlotManager pm = new PlotManager()
	
	def plotters = [:]

	def stop(){
		if(th!=null){
			if( th.isAlive()){
				th.interrupt()
			}
		}
	}

	def initPlot(){

//		pm.addFrame("P1")
//		pm.addPen("P1","CPI")
//
//		pm.addFrame("P2")
//		pm.addPen("P2","就业率")
//
//		pm.show()
		Plotter p1 = new Plotter("P1")
		plotters["P1"] = p1
		p1.reset()
		p1.addPen("CPI")
		p1.show()

		Plotter p2 = new Plotter("P2")
		plotters["P2"] = p2
		p2.reset()
		p2.addPen("就业率")
		p2.show()


	}
	def setup(){

		if(SEED_FIXED==1){
			rnd = new Random(SEED)
			println "固定随机种子！"
		}else{
			rnd = new Random(System.currentTimeMillis())
			println "不固定随机种子！"
		}
		AgentInitializer hInit = new AgentInitializer("scripts/HouseHoldSettings.groovy")
		hInit.rnd = rnd

		AgentInitializer fInit = new AgentInitializer("scripts/FirmSettings.groovy")
		fInit.rnd = rnd

		// 创建households
		(1..H_NUM).each { int i ->
			def h = new HouseHold(who:i,allFirms:firms)
			hInit.init(h)
			households.add(h)

		}

		// 创建firms
		(1..F_NUM).each { int i ->
			def f = new Firm(who:i)
			fInit.init(f)
			firms.add(f)

		}

//		households[0].inspected = true
//		firms[1].inspected = true

		// 随机创建A B links
		households.each { HouseHold h->

			// 1家工作公司
			h.workingFirm = (Firm)oneof(firms)
			h.workingFirm.addWorker(h)

			// 7家购物公司
			h.shoppingFirms = (ArrayList<Firm>)nof(SHOPPING_FIRMS_NUM,firms)
			h.shoppingFirms.each { Firm f ->
				f.addClient(h)
			}
		}

		initPlot()

	}

	def oneRun(){

		tickToMonthDay()
		//println "Day: " + monthDay

		// 月初
		if(monthDay == 1){
			println "月初"
			firms.each { Firm f ->f.initMonth()}
			households.each { HouseHold h -> h.initMonth()}

		}

		//购物的顺序涉及到谁的需求能满足
		//如果一直都是按家庭的顺序购物，则总是前几个家庭能满足需求，后面的就总是无法满足需求
		def order = (0..households.size() - 1).toList()
		shuffle(order)
		//println "order:${order}"
		order.each { int i ->
			HouseHold h = households[i]
			h.shopping()
		}

		firms.each { Firm f ->
			f.produce()

		}

		if(monthDay == DAYS_OF_MONTH){

			println "月末"
			firms.each{ it.endMonth() }
			households.each{it.endMonth()}

			updatePlot()
			println " "
		}

		//println ""

		tick()
	}

	def updatePlot(){
		def cpi = mean(firms.mPrice).round(3)
		println "CPI:" + cpi
//		pm.plot("CPI",cpi)
//
		def er = households.findAll{it.workingFirm!=null}.size()/households.size()
		println "er:" + er
//		pm.plot("就业率",er)
		
		plotters["P1"].plot("CPI",cpi)
		plotters["P2"].plot("就业率",er)
	}

	def printData(){
		long time  = System.currentTimeMillis() - start
		println "总ticks:：" + ticks
		println "总月份："+ (float)ticks / DAYS_OF_MONTH
		println "年数：" + (float)ticks / DAYS_OF_MONTH / 12
		println "用时：" + time / 1000
		println "每tick平均："+ time / 1000 / ticks
		println "每月平均："+ time / 1000 / ticks * this.monthDay

	}

	def run()  {

		pm.reset()
		long start = System.currentTimeMillis()

		def endlessRun = {
			while(true){
				oneRun()
				if (th.isInterrupted()) {
					break;
				}
			}
		}

		def runto = {
			(1..runs).each{ oneRun() }
		}

		if (runs<=0){

			println "新线程"
			th = new Thread()
			th = Thread.start endlessRun

			//th.join()

		}else{
			runto()
		}


	}

	// tick转为几号，0 -> 1st,2 -> 2nd
	def tickToMonthDay(){
		monthDay = ticks % DAYS_OF_MONTH + 1
	}

	def tick(){
		ticks ++
	}

	def printHouseHolds(){
		households.each { HouseHold h->
			println h.toString(true) + "\n"
		}
	}

	def printFirms(){
		firms.each{ Firm f ->
			println f.toString(true) + "\n"

		}
	}

	@CompileStatic
	static ArrayList nof(int n,ArrayList aa){

		if (aa.size() <= n){
			return (ArrayList)aa
		}

		List order = (0..aa.size()-1).toList()

		shuffle(order)

		return (ArrayList)aa[order[0..n-1]]

	}

	@CompileStatic
	def static oneof(ArrayList aa){
		ArrayList result = nof(1,aa)
		if(result != null){
			return result[0]
		}
		return null
	}

	@CompileStatic
	def static shuffle(List list){
		Collections.shuffle(list,rnd)
	}

	@CompileStatic
	def static random(){
		return rnd.nextFloat()
	}

	def static mean(List l){
		return ((float)l.sum()/l.size()).round(3)
	}
}
/*
 * 
 * 
 * 
 * 
 * 
 * 
 */
